from django.db import models
from django.apps import apps
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager

from django.utils.translation import gettext_lazy as _

# Create your models here.
# 基于用户管理模型基类模型创建新的用户管理模型
class UserManager(BaseUserManager):
    use_in_migrations = True
    #  sourcery skip: avoid-builtin-shadow
    # Create and save a user with the given id, password.
    def create_user(self, id, password, **extra_fields):
        if not id:
            raise ValueError("The given id must be set")
        # 从全局应用程序注册表中查找真实的模型类，以便在迁移中使用此管理器方法。因为管理员们根据定义是在真正的模型上工作。
        GlobalUserModel = apps.get_model(
            self.model._meta.app_label, self.model._meta.object_name
        )
        # 从全局应用程序中获取id
        id = GlobalUserModel.normalize_username(id)

        # 创建并保存用户
        user = self.model(id=id, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    # 创建超级管理员用户
    def create_superuser(self, id, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("status", 1)
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")
        return self.create_user(id, password, **extra_fields)


# 创建一个用户抽象模型类
class AbstractUser(AbstractBaseUser, PermissionsMixin):

    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    id and password are required. Other fields are optional.
    """
    id = models.CharField(_("工号"),max_length=10, unique=True, primary_key=True)
    password = models.CharField(max_length=255)
    is_staff = models.BooleanField(
        _("staff status"),
        default=False,
        help_text=_(
            "Designates whether the user can log into this admin site."),
    )

    # 用户名
    username = models.CharField(
        _("用户名"),
        max_length=15,blank=True, null=True
    )
    email = models.EmailField(
        _("email address"), unique=True, null=True, blank=True)

    objects = UserManager()

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "id"

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")
        abstract = True


# 创建一个基类模型，将公共字段定义到基类模型中，公共字段有status、create_time、update_time、create_user、update_user
class BaseModel(models.Model):
    """
    基类模型，定义公共字段
    """
    status_choices = [
        (0, 'New'),
        (1, 'Active'),
        (2, 'Frozen')
    ]
    status = models.SmallIntegerField(default=0,choices=status_choices, verbose_name="状态")
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    creator = models.CharField(
        null=True, blank=True, verbose_name='建立人员', max_length=10)
    updater = models.CharField(
        null=True, blank=True, max_length=10, verbose_name='更新人员')

    class Meta:
        abstract = True
        # 按照更新时间排序
        ordering = ['-update_time']

# 基于基类定义部门类，部门类关联自身，为上级部门，新增字段有name，title，dept
class Dept(BaseModel):
    name = models.CharField(max_length=20, null=True, blank=True, verbose_name="部门名称")
    title = models.CharField(max_length=255, null=True, blank=True, verbose_name="部门标题")
    dept = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, verbose_name="上级部门", related_name="up_dept")

    class Meta:
        verbose_name = "部门"
        verbose_name_plural = "部门"
    # 默认对象显示name字符
    def __str__(self):
        return self.name

# 基于用户抽象类和基类模型创建新的用户模型，新增字段mobile，id_card，dept
class User(AbstractUser, BaseModel):
    mobile = models.CharField(max_length=11, null=True, blank=True, verbose_name="手机号码")
    id_card = models.CharField(max_length=18, null=True, blank=True, verbose_name="身份证号码")
    dept = models.ForeignKey(Dept, on_delete=models.CASCADE, null=True, blank=True, verbose_name="部门", related_name="user_dept")

    class Meta:
        verbose_name = "用户"
        verbose_name_plural = "用户"